/*
 * sysmo 客户端配置封装类。
 * Copyright (C) 2009  YuLicheng
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.sysmo.server.util;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

/**
 * 服务器配置封装类。此类保存了服务器启动时从配置文件中读取的配置信息。
 *
 * @author YuLicheng
 */
public class ServerSettings {
    /**
     * 设置Map，当此类被实例化过一次后，即可直接访问此元素。
     */
    public HashMap<String, String> settingMap;
    /**
     * 保存最近被实例化的对象。
     */
    public static ServerSettings settings = null;

    /**
     * 创建配置实例。
     *
     * @param filename 配置文件名。
     * @throws IOException
     * @throws ParserConfigurationException
     * @throws SAXException
     */
    public ServerSettings(String filename) throws IOException,
            ParserConfigurationException, SAXException {
        settingMap = new HashMap<String, String>();
        File settingFile = new File(filename);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        Document doc =  factory.newDocumentBuilder().parse(settingFile);
        walkNode(doc.getFirstChild(), "");
        settings = this;
    }

    /**
     * 遍历配置文件中每个节点。
     *
     * @param root 开始遍历的节点。
     * @param prefix 名称前缀。
     */
    private void walkNode(Node root, String prefix) {
        for (Node node = root.getFirstChild(); node != null;
                node = node.getNextSibling()) {
            short type = node.getNodeType();
            String nodePath = prefix + "/" + node.getNodeName();
            switch (type) {
                case Node.CDATA_SECTION_NODE: //fall through
                case Node.TEXT_NODE:
                    if (node.getNextSibling() != null  ||
                            node.getPreviousSibling() != null) {
                        break;
                    }
                    settingMap.put(prefix, node.getNodeValue());
                    break;
                case Node.ELEMENT_NODE:
                    walkNode(node, nodePath);
                    break;
                case Node.COMMENT_NODE: //忽略注释
                    break;
                default:
                    System.out.println("配置文件中包含不支持的节点类型：" + type +
                        "(" + nodePath + ")");
                    break;
            }
        }
    }
}
